#!/usr/bin/env python
#coding:utf-8

import PCL730
import RTControl as RTC
import RTControl.Cylinder as Cylinder
import ControlThings as CT
from Debug import debug, error
import Globals
import time
import Winio

class DOOutputor(RTC.Outputor.Outputor):
    def __init__(self, pci1730, chn):
        RTC.Outputor.Outputor.__init__(self)
        self.pci1730 = pci1730
        self.chn = chn
    
    def Output(self, value):
        self.pci1730.WriteDOBit(value, self.chn)

class DICollector(RTC.CyclicCollector):
    def __init__(self, domain):
        RTC.CyclicCollector.__init__(self, 0.2)
        self.domain = domain
    
    def OneCyclic(self):
        self.domain.UpdateDIVariable()

class ControlDomain:
    def __init__(self):
        self.__pci1730_baseaddr = 0xc800
        
        self.v_input = []
        
        self.__pci1730 = PCL730.PCL730(self.__pci1730_baseaddr)
        
        self.__CreateInputVariable()
        self.__CreateOutputVariable()
        self.__CreateObjects()
        
    def BeginWork(self):
        Winio.InitializeWinIo()
        self.dicollector = DICollector(self)
        
        self.dicollector.Start()
    
    def EndWork(self):
        self.dicollector.Stop()
        Winio.ShutdownWinIo()
        
    def UpdateDIVariable(self):
        vs = self.__pci1730.ReadDI()
        for i, v in enumerate(self.v_input):
            v.SetValue(vs & (0x0001 << i))
                
    def GetSensorCylinder(self):
        return self.sensorcylinder
    
    def GetClampCylinder(self):
        return self.clamplinder
    
    def __CreateInputVariable(self):
        self.v_scram = RTC.Digital(RTC.INPUT_VARIABLE, 'Scram')                      #急停
        self.v_input.append(self.v_scram)
        self.v_start = RTC.Digital(RTC.INPUT_VARIABLE, 'Start')                      #启动
        self.v_input.append(self.v_start)
        self.v_reset = RTC.Digital(RTC.INPUT_VARIABLE, 'Reset')                      #复位
        self.v_input.append(self.v_reset)
        self.v_contrlmode = RTC.Digital(RTC.INPUT_VARIABLE, 'ControlMode')           #手动/自动模式切换
        self.v_input.append(self.v_contrlmode)
        self.v_ready = RTC.Digital(RTC.INPUT_VARIABLE, 'Ready')                      #准备
        self.v_input.append(self.v_ready)
        self.v_lsensorlimit = RTC.Digital(RTC.INPUT_VARIABLE, 'LeftSensorLimit')     #左传感器气缸极限位置
        self.v_input.append(self.v_lsensorlimit)
        self.v_lsensorhome = RTC.Digital(RTC.INPUT_VARIABLE, 'LeftSensorHome')       #左传感器气缸初始位置
        self.v_input.append(self.v_lsensorhome)
        self.v_rsensorlimit = RTC.Digital(RTC.INPUT_VARIABLE, 'RightSensorLimit')    #右传感器气缸极限位置
        self.v_input.append(self.v_rsensorlimit)
        self.v_rsensorhome = RTC.Digital(RTC.INPUT_VARIABLE, 'RightSensorHome')      #右传感器气缸初始位置
        self.v_input.append(self.v_rsensorhome)
        self.v_lclamplimit = RTC.Digital(RTC.INPUT_VARIABLE, 'LeftClampLimit')       #右压紧气缸极限位置
        self.v_input.append(self.v_lclamplimit)
        self.v_lclamphome = RTC.Digital(RTC.INPUT_VARIABLE, 'LeftClampHome')         #右压紧气缸初始位置
        self.v_input.append(self.v_lclamphome)
        self.v_rclamplimit = RTC.Digital(RTC.INPUT_VARIABLE, 'RightClampLimit')      #右压紧气缸极限位置
        self.v_input.append(self.v_rclamplimit)
        self.v_rclamphome = RTC.Digital(RTC.INPUT_VARIABLE, 'RightClampHome')        #右压紧气缸极限位置
        self.v_input.append(self.v_rclamphome)
        self.v_typesensor1 = RTC.Digital(RTC.INPUT_VARIABLE, 'TypeSensor1')          #
        self.v_input.append(self.v_typesensor1)
        self.v_typesensor2 = RTC.Digital(RTC.INPUT_VARIABLE, 'TypeSensor2')
        self.v_input.append(self.v_typesensor2)
        
        self.v_scram.Bind(RTC.EVT_PEGATIVE_EDGE, self.OnScramDown)                   #下降沿急停生效
        self.v_start.Bind(RTC.EVT_POSITIVE_EDGE, self.OnStart)                       #上升沿启动生效
        self.v_reset.Bind(RTC.EVT_POSITIVE_EDGE, self.OnReset)                       #上升沿复位生效
        self.v_ready.Bind(RTC.EVT_POSITIVE_EDGE, self.OnReady)
        self.v_ready.Bind(RTC.EVT_PEGATIVE_EDGE, self.OnUnready)
        self.v_lsensorhome.Bind(RTC.EVT_POSITIVE_EDGE, self.OnLeftSensorHome)
        self.v_rsensorhome.Bind(RTC.EVT_POSITIVE_EDGE, self.OnRightSensorHome)
        
    def __CreateOutputVariable(self):
        self.v_red = RTC.Digital(RTC.OUTPUT_VARIABLE, 'Red', ioobj = DOOutputor(self.__pci1730, 0))
        self.v_yellow = RTC.Digital(RTC.OUTPUT_VARIABLE, 'Yellow', ioobj = DOOutputor(self.__pci1730, 1))
        self.v_green = RTC.Digital(RTC.OUTPUT_VARIABLE, 'Green', ioobj = DOOutputor(self.__pci1730, 2))
        self.v_sensorstretch = RTC.Digital(RTC.OUTPUT_VARIABLE, 'SensorStretch', ioobj = DOOutputor(self.__pci1730, 4))
        self.v_sensorshrink = RTC.Digital(RTC.OUTPUT_VARIABLE, 'SensorShrink', ioobj = DOOutputor(self.__pci1730, 3))
        #self.v_clampstretch = RTC.Digital(RTC.OUTPUT_VARIABLE, 'ClampStretch', ioobj = DOOutputor(self.__pci1730, 5))
        self.v_clampstretch = RTC.Digital(RTC.OUTPUT_VARIABLE, 'ClampStretch', ioobj = DOOutputor(self.__pci1730, 7))
        self.v_clampshrink = RTC.Digital(RTC.OUTPUT_VARIABLE, 'ClampShrink', ioobj = DOOutputor(self.__pci1730, 6))
        
    def __CreateObjects(self):
        self.sensorcylinder = CT.MyAirCylinder(Cylinder.DoubleControl(self.v_sensorstretch, self.v_sensorshrink),\
                                                self.v_lsensorlimit, self.v_rsensorlimit, \
                                                self.v_lsensorhome, self.v_rsensorhome)
        '''
        self.sensorcylinder = CT.MyAirCylinder(Cylinder.SingleControl(self.v_sensorshrink),\
                                                self.v_lsensorlimit, self.v_rsensorlimit,\
                                                 self.v_lclamphome, self.v_rsensorhome)
        '''
        self.clamplinder = CT.MyAirCylinder(Cylinder.SingleControl(self.v_clampstretch), \
                                            self.v_lclamplimit, self.v_rclamplimit, \
                                            self.v_lclamphome, self.v_rclamphome)
        
    def OnScramDown(self, evt): #  急停功能。    
        self.sensorcylinder.Stop()  #传感器气缸停止， cylinder  气缸
        self.clamplinder.Stop() #压紧气缸停止
        
    def OnReady(self, evt):
        app.domain.OnPartReady()
        
    def OnUnready(self, evt):
        app.domain.OnPartUnready()
    
    def OnReset(self, evt):
        app.domain.OnResetButton()
    
    def OnStart(self, evt):
        app.domain.OnStartButton()
        
    def OnLeftSensorHome(self, evt):
        app.domain.OnLeftSensorHome()
    
    def OnRightSensorHome(self, evt):
        app.domain.OnRightSensorHome()
    
    def IsScram(self):
        return not self.v_scram.GetValue()
    
    def IsAuto(self):
        return self.v_contrlmode.GetValue()
    
    def IsManual(self): #是否是手动
        return not self.v_contrlmode.GetValue()
    
    def IsReady(self):
        return self.v_ready.GetValue()
    
    def GetSensorType(self):
        v1 = self.v_typesensor1.GetValue()
        v2 = self.v_typesensor2.GetValue()
        
        if v1 and v2:
            return 2
        elif v1 and not v2:
            return 1
        elif not v1 and not v2:
            return 0
        return -1
    
    def ShortWarn(self, timeout = 3.0):
        def _ShortWarn(timeout):
            self.Red()
            time.sleep(timeout)
            self.Green()
        RTC.AddTask(_ShortWarn, timeout)
    
    def Red(self):
        self.v_red.SetValue(True)
        self.v_green.SetValue(False)
        self.v_yellow.SetValue(False)
        
    def Yellow(self):
        self.v_yellow.SetValue(True)
        self.v_red.SetValue(False)
        self.v_green.SetValue(False)
        
    def Green(self):
        self.v_green.SetValue(True)
        self.v_red.SetValue(False)
        self.v_yellow.SetValue(False)
        
    def Sequnce(self, only_sensor = False):
        if not only_sensor:
            self.clamplinder.Stretch(0)
            time.sleep(1)
        self.sensorcylinder.Stretch(6)
        
    def UnSequnce(self):
        self.sensorcylinder.Shrink(6)
        self.clamplinder.Shrink(0)